package com.yanqu.road.entity.activity.daomu.pvp;

import com.yanqu.road.entity.activity.daomu.pvp.helper.CollisionHelper;
import com.yanqu.road.entity.activity.daomu.pvp.helper.CoordinateHelper;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

import static com.yanqu.road.entity.activity.daomu.pvp.helper.CoordinateHelper.*;

/**
 * 盗墓笔记子弹类型
 */
public class DaoMuPvpBulletData {

    /**
     * 子弹唯一标识
     */
    private String bulletId;

    /**
     * 发射人
     */
    private long userId;

    /**
     * 发射时间
     */
    private long createTime;

    /**
     * 移动速度
     * 角度/每毫秒
     */
    private double speed;

    /**
     * 初始角度
     */
    private double initialAngle;

    /**
     * 击中的时间列表
     */
    private Map<String, Long> attackTimeMap = new ConcurrentHashMap<>();


    public DaoMuPvpBulletData() {

    }

    public DaoMuPvpBulletData(String bulletId, long userId) {
        this.bulletId = bulletId;
        this.userId = userId;
        this.createTime = System.currentTimeMillis();
    }


    /**
     * 获取线段起始点x坐标
     *
     * @param time
     * @return
     */
    public double getStartX(Coordinate coordinate, double time) {
        double angle = (initialAngle + speed * time) % 360; // 角度
        return coordinate.getX() + ROLE_RADIUS * Math.cos(Math.toRadians(angle)); //起始点在圆上，因此需要加上半径   50为人物半径
    }

    /**
     * 获取线段起始点y坐标
     *
     * @param time
     * @return
     */
    public double getStartY(Coordinate coordinate, double time) {
        double angle = (initialAngle + speed * time) % 360; // 角度
        return coordinate.getY() - ROLE_RADIUS * Math.sin(Math.toRadians(angle)); //起始点在圆上，因此需要加上半径
    }

    /**
     * 获取线段结束点x坐标
     *
     * @param time
     * @return
     */
    public double getEndX(Coordinate coordinate, double time) {
        double angle = (initialAngle + speed * time) % 360; // 角度
        return coordinate.getX() + (ROLE_RADIUS + BULLET_LENGTH) * Math.cos(Math.toRadians(angle)); //终点在圆外，因此需要加上线段长度
    }

    /**
     * 获取线段结束点y坐标
     *
     * @param time
     * @return
     */
    public double getEndY(Coordinate coordinate, double time) {
        double angle = (initialAngle + speed * time) % 360; // 角度
        return coordinate.getY() - (ROLE_RADIUS + BULLET_LENGTH) * Math.sin(Math.toRadians(angle)); //终点在圆外，因此需要加上线段长度
    }

    public double getCenterX(Coordinate coordinate, double time) {
        return (getStartX(coordinate, time) + getEndX(coordinate, time)) / 2;
    }

    public double getCenterY(Coordinate coordinate, double time) {
        return (getStartY(coordinate, time) + getEndY(coordinate, time)) / 2;
    }

    /**
     * 计算向量叉积
     * @param x1
     * @param y1
     * @param x2
     * @param y2
     * @return
     */
    protected double crossProduct(double x1, double y1, double x2, double y2) {
        return x1 * y2 - x2 * y1;
    }


    /**
     * 检查线段是否与其他圆交叉
     *
     * @param otherCenterX
     * @param otherCenterY
     * @return
     */
    public boolean intersectsWithCircle(Coordinate coordinate, double otherCenterX, double otherCenterY, long time) {
        double offsetTime = time - createTime;
        double startX = getStartX(coordinate, offsetTime);
        double startY = getStartY(coordinate, offsetTime);
        double endX = getEndX(coordinate, offsetTime);
        double endY = getEndY(coordinate, offsetTime);
        double dx = endX - startX;
        double dy = endY - startY;
        double a = dx * dx + dy * dy;
        double b = 2 * (dx * (startX - otherCenterX) + dy * (startY - otherCenterY));
        double c = (startX - otherCenterX) * (startX - otherCenterX) + (startY - otherCenterY) * (startY - otherCenterY) - ROLE_RADIUS * ROLE_RADIUS;  // 人物受击半径
        if (-b < 0)
            return (c < 0);
        if (-b < (2 * a))
            return (4 * a * c - b * b < 0);
        return (a + b + c < 0);
    }


    /**
     * 检查线段是否与其他线段交叉
     *
     * @param other
     * @param time
     * @return
     */
    public boolean intersectsWithSegment(Coordinate myCoordinate, DaoMuPvpBulletData other, Coordinate otherCoordinate, double time) {
        double myOffsetTime = time - createTime;
        double otherOffsetTime = time - other.getCreateTime();

        double x1 = getStartX(myCoordinate, myOffsetTime);
        double x2 = getEndX(myCoordinate, myOffsetTime);
        double x3 = other.getStartX(otherCoordinate, otherOffsetTime);
        double x4 = other.getEndX(otherCoordinate, otherOffsetTime);

        double y1 = getStartY(myCoordinate, myOffsetTime);
        double y2 = getEndY(myCoordinate, myOffsetTime);
        double y3 = other.getStartY(otherCoordinate, otherOffsetTime);
        double y4 = other.getEndY(otherCoordinate, otherOffsetTime);

        // 判断线段是否完全重叠
        if ((x1 == x3 && y1 == y3 && x2 == x4 && y2 == y4) || (x1 == x4 && y1 == y4 && x2 == x3 && y2 == y3)) {
            return true;
        }

        // 判断线段是否部分重叠
        boolean overlap = (x1 <= x3 && x3 <= x2 && y1 <= y3 && y3 <= y2) ||
                (x1 <= x4 && x4 <= x2 && y1 <= y4 && y4 <= y2) ||
                (x3 <= x1 && x1 <= x4 && y3 <= y1 && y1 <= y4) ||
                (x3 <= x2 && x2 <= x4 && y3 <= y2 && y2 <= y4);
        if (overlap) {
            return true;
        }

        //使用向量叉积判断线段是否相交
        double d1 = crossProduct(x1 - x3, y1 - y3, x4 - x3, y4 - y3); // (x1-x3)*(y4-y3) - (y1-y3)*(x4-x3)
        double d2 = crossProduct(x2 - x3, y2 - y3, x4 - x3, y4 - y3); // (x2-x3)*(y4-y3) - (y2-y3)*(x4-x3)
        double d3 = crossProduct(x3 - x1, y3 - y1, x2 - x1, y2 - y1); // (x3-x1)*(y2-y1) - (y3-y1)*(x2-x1)
        double d4 = crossProduct(x4 - x1, y4 - y1, x2 - x1, y2 - y1); // (x4-x1)*(y2-y1) - (y4-y1)*(x2-x1)

        return (d1 * d2 < 0) && (d3 * d4 < 0);
    }

    public List<Coordinate> getRectanglePoints(Coordinate coordinate, double offsetTime) {

        // 高
        double a = BULLET_WIDTH;
        // 宽
        double b = BULLET_LENGTH;
        double r = ROLE_RADIUS + b / 2;
        double angle = Math.toRadians((initialAngle + speed * offsetTime) % 360); // 角度转换为弧度

        double centerX = coordinate.getX() + r * Math.cos(angle); // 线段起始点x坐标
        double centerY = coordinate.getY() - r * Math.sin(angle); // 线段起始点y坐标

        // 计算未旋转的矩形四个顶点
        List<Coordinate> points = new ArrayList<>();
        points.add(new Coordinate(centerX - b / 2, centerY + a / 2)); // 左上
        points.add(new Coordinate(centerX + b / 2, centerY + a / 2)); // 右上
        points.add(new Coordinate(centerX + b / 2, centerY - a / 2)); // 右下
        points.add(new Coordinate(centerX - b / 2, centerY - a / 2)); // 左下

        // 对每个顶点进行旋转(绕着子弹的圆心旋转)
        for (Coordinate point : points) {
            double dx = point.getX() - centerX;
            double dy = point.getY() - centerY;
            double rotatedX = centerX + dx * Math.cos(angle) + dy * Math.sin(angle); // 顺时针旋转
            double rotatedY = centerY - dx * Math.sin(angle) + dy * Math.cos(angle); // 顺时针旋转
            point.setX(rotatedX);
            point.setY(rotatedY);
        }

        return points;
    }

    /**
     * 子弹与子弹的碰撞
     *
     * @param other
     * @param time
     * @return
     */
    public boolean intersectsWithRectangle(Coordinate myCoordinate, DaoMuPvpBulletData other, Coordinate otherCoordinate, double time) {
        return CollisionHelper.intersectsWithRectangle(getRectanglePoints(myCoordinate, time - createTime), other.getRectanglePoints(otherCoordinate, time - other.getCreateTime()));
    }

    /**
     * 检测子弹与其他矩形的碰撞
     * 人物、宝箱、怪物用
     */
    public boolean intersectsWithRectangle(Coordinate myCoordinate, Coordinate otherCoordinate, double width, double height, double time) {
        // 获取目标矩形的四个角的点坐标
        List<Coordinate> points = new ArrayList<>();
        points.add(new Coordinate(otherCoordinate.getX() - width / 2, otherCoordinate.getY() + height / 2)); // 左上
        points.add(new Coordinate(otherCoordinate.getX() + width / 2, otherCoordinate.getY() + height / 2)); // 右上
        points.add(new Coordinate(otherCoordinate.getX() + width / 2, otherCoordinate.getY() - height / 2)); // 右下
        points.add(new Coordinate(otherCoordinate.getX() - width / 2, otherCoordinate.getY() - height / 2)); // 左下
        return CollisionHelper.intersectsWithRectangle(getRectanglePoints(myCoordinate, time - createTime), points);
    }


    /**
     * 矩形与圆形的碰撞
     *
     * @param circleCenter
     * @param radius
     * @param time
     * @return
     */
    public boolean intersectsWithCircle(Coordinate coordinate, Coordinate circleCenter, double radius, double time) {
        return CollisionHelper.intersectsWithCircle(getRectanglePoints(coordinate, time - createTime), circleCenter, radius);
    }



    public String getBulletId() {
        return bulletId;
    }

    public void setBulletId(String bulletId) {
        this.bulletId = bulletId;
    }

    public long getUserId() {
        return userId;
    }

    public void setUserId(long userId) {
        this.userId = userId;
    }

    public long getCreateTime() {
        return createTime;
    }

    public void setCreateTime(long createTime) {
        this.createTime = createTime;
    }

    public double getSpeed() {
        return speed;
    }

    public void setSpeed(double speed) {
        this.speed = speed;
    }

    public double getInitialAngle() {
        return initialAngle;
    }

    public void setInitialAngle(double initialAngle) {
        this.initialAngle = initialAngle;
    }

    public Map<String, Long> getAttackTimeMap() {
        return attackTimeMap;
    }

    public void setAttackTimeMap(Map<String, Long> attackTimeMap) {
        this.attackTimeMap = attackTimeMap;
    }
}
